#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : user.py
@TIME          : 2025/02/27 15:23:00
@AUTHOR        : chenlip
@VERSION       : 0.0.1
@DESCRIPTION   : 用户模块数据模型定义，包括用户主表、用户等级表、用户附加信息表、用户元数据信息表、用户行为日志表
'''

from sqlalchemy import Column, Integer, String, TIMESTAMP, DateTime, Text, Float, JSON, ForeignKey, Index
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from flask_login import UserMixin

from init_app import sqldb as db

class User(db.Model, UserMixin):
    """用户主表：存储用户基本信息，包括用户ID、昵称、登录名、密码哈希值等"""
    __tablename__ = 't_user'
    
    user_id = Column(Integer, primary_key=True, comment='用户唯一标识（雪花算法生成）;')
    nickname = Column(String(255), nullable=False, comment='用户昵称（不能包含特殊字符）')
    loginname = Column(String(20), unique=True, comment='用户名（唯一约束，支持中文/英文/数字，正则校验：^[\u4e00-\u9fa5a-zA-Z0-9_]{2,20}$）')
    password_hash = Column(String(255), nullable=False, comment='密码哈希值（bcrypt加密，固定60字符，盐值长度12位）')
    email = Column(String(50), unique=True, comment='邮箱（唯一约束，格式校验）')
    phone = Column(String(15), comment='手机号（唯一约束，国际区号+号码，如+8613812345678）')
    qq = Column(String(15), comment='QQ号')
    birthday = Column(DateTime, comment='生日')
    user_sex = Column(Integer, default=0, comment='性别（0-未知，1-男，2-女）')
    avatar = Column(String(255), default='/static/avatar/d_logo.jpg', comment='头像地址（默认/static/avatar/d_logo.jpg）')
    description = Column(String(255), comment='用户简介')
    status = Column(Integer, default=0, comment='状态（1-active正常 / 0-banned封禁 / 4-deleted注销）')
    role = Column(Integer, default=0, comment='用户角色（0-注册用户，1-管理员，2-版主，3-副版主）')
    is_ai_user = Column(Integer, default=0, comment='是否为AI虚拟用户（0-非ai虚拟用户，1-ai虚拟用户）')
    real_name = Column(String(100), comment='真实姓名（AES加密存储）')
    id_card = Column(String(30), comment='身份证号（AES加密存储）')
    security_question = Column(JSON, comment='密保问题（格式：{"question1":"...", "answer1":"..."}）')
    create_time = Column(TIMESTAMP, server_default=func.current_timestamp(), comment='注册时间')
    update_time = Column(TIMESTAMP, server_default=func.current_timestamp(), 
                        onupdate=func.current_timestamp(), comment='最后编辑时间（自动更新）')
    
    # 关系定义
    extension = relationship("UserExtension", uselist=False, back_populates="user", cascade="all, delete-orphan")
    meta_data = relationship("UserMeta", back_populates="user", cascade="all, delete-orphan")
    action_logs = relationship("UserActionLog", back_populates="user", cascade="all, delete-orphan")
    
    # 索引定义
    __table_args__ = (
        Index('idx_user_email', email),
        Index('idx_user_phone', phone),
        Index('idx_user_status', status),
        {'comment': '用户主表'}
    )

    def get_id(self):
        return self.user_id
    
    def has_role(self, role):
        return self.role == role
    
    # 附件属性：检查用户是否为管理员
    @property
    def is_admin(self):
        return self.role == 1
    
    @property
    def is_authenticated(self):
        # 例如，添加额外的认证条件，如账户未被锁定
        return True and self.status == 1  # 假设status=1表示正常状态
    
    @property
    def is_ai(self):
        # 例如，添加额外的认证条件，如账户未被锁定
        return self.is_ai_user == 1  # 假设is_ai_user=1表示AI用户

    def __repr__(self):
        return '<User %r>' % self.nickname+':'+self.loginname+':'+str(self.user_id)


class UserLevel(db.Model):
    """用户等级表：定义用户等级体系，包含等级名称、最低积分要求及特权配置"""
    __tablename__ = 't_user_level'
    
    level_id = Column(Integer, primary_key=True, comment='等级ID（从1开始递增）')
    level_name = Column(String(20), nullable=False, unique=True, comment='等级名称（如`青铜战士`/`钻石元老`）')
    min_points = Column(Integer, nullable=False, comment='升级所需最低积分（严格递增校验）')
    privileges = Column(JSON, comment='特权配置（格式示例：{"daily_upload_limit":100, "signin_bonus":50}）')
    badge_icon = Column(String(255), comment='等级徽章图标路径')
    description = Column(Text, comment='等级特权描述（前端展示用）')
    
    # 关系定义
    users_extension = relationship("UserExtension", back_populates="level")
    
    # 索引定义
    __table_args__ = (
        Index('uk_level_name', level_name, unique=True),
        Index('idx_min_points', min_points.desc()),
        {'comment': '用户等级表'}
    )

    def __repr__(self):
        return '<UserLevel %r>' % self.level_name+':'+str(self.level_id)


class UserExtension(db.Model):
    """用户附加信息表：用户的扩展信息，包括隐私设置、积分、等级等"""
    __tablename__ = 't_user_extension'
    
    user_id = Column(Integer, ForeignKey('t_user.user_id', ondelete='CASCADE'), 
                    primary_key=True, comment='主键且外键关联user.user_id')
    privacy_settings = Column(JSON, comment='隐私设置（示例：{"show_email":false,"hide_last_login":true}）')
    current_points = Column(Integer, default=10, comment='当前积分（与points_history表实时同步）')
    current_level = Column(Integer, ForeignKey('t_user_level.level_id'), 
                          default=1, comment='外键关联user_level.level_id（初始值为1级）')
    last_login_time = Column(TIMESTAMP, comment='最后一次登录时间')
    total_online = Column(Integer, default=0, comment='累计在线总时长（秒，定时任务统计）')
    
    # 关系定义
    user = relationship("User", back_populates="extension")
    level = relationship("UserLevel", back_populates="users_extension")
    
    # 索引定义
    __table_args__ = (
        Index('idx_user_extension_level', current_level),
        Index('idx_user_extension_points', current_points.desc()),
        {'comment': '用户附加信息表'}
    )

    def __repr__(self):
        return '<UserExtension %r>' % self.user_id


class UserMeta(db.Model):
    """用户元数据信息表：用户元数据信息，包括微信账户、支付宝账户、qq账户等"""
    __tablename__ = 't_user_meta'
    
    meta_id = Column(Integer, primary_key=True, comment='元数据ID')
    user_id = Column(Integer, ForeignKey('t_user.user_id', ondelete='CASCADE'), 
                    nullable=False, comment='外键关联user.user_id')
    meta_group = Column(String(50), default='other_settings', comment='元数据分组，固定分组：wechat_settings微信账户设置；zhifubao_settings支付宝账户设置；AI_user_settings虚拟用户属性设置；other_settings其他设置')
    meta_key = Column(String(50), nullable=False, comment='键名（如achievement_badge）')
    meta_value = Column(Text, comment='键值（如"年度活跃用户"）')
    create_time = Column(TIMESTAMP, server_default=func.current_timestamp(), comment='创建时间')
    update_time = Column(TIMESTAMP, server_default=func.current_timestamp(), 
                        onupdate=func.current_timestamp(), comment='修改时间（自动更新）')
    
    # 关系定义
    user = relationship("User", back_populates="meta_data")
    
    # 索引定义
    __table_args__ = (
        Index('idx_user_meta_group', user_id, meta_group),
        Index('idx_user_meta_key', user_id, meta_key),
        {'comment': '用户元数据信息表'}
    )

    def __repr__(self):
        return '<UserMeta %r>' % str(self.meta_id)+':'+self.meta_key+':'+self.meta_value+':'+str(self.user_id)


class UserActionLog(db.Model):
    """用户行为日志表：记录用户的各类操作行为，如登录、发帖、点赞、收藏等"""
    __tablename__ = 't_user_action_log'
    
    log_id = Column(Integer, primary_key=True, comment='日志ID（时序ID生成）')
    user_id = Column(Integer, ForeignKey('t_user.user_id', ondelete='CASCADE'), 
                    nullable=False, comment='外键关联user.user_id')
    action_type = Column(Integer, nullable=False, 
                        comment='行为类型（login登录/logout下线/follow关注/like点赞/collect收藏/add增加/edit修改/del删除/下载/分享）')
    target_type = Column(Integer, nullable=False, 
                        comment='对象类型（1-用户；2-主贴；3-版块；4-回复；5-资源）')
    target_id = Column(Integer, nullable=False, comment='关联对象ID')
    client_info = Column(JSON, comment='客户端信息（示例：{"ip":"192.168.1.1", "os":"Android", "browser":"Chrome"}）')
    duration = Column(Integer, comment='在线时长（秒，仅对login和topic_view有效）')
    create_time = Column(TIMESTAMP, server_default=func.current_timestamp(), comment='行为时间')
    
    # 为提取IP地址创建虚拟列
    client_ip = Column(String(45), comment='客户端IP地址')
    
    # 关系定义
    user = relationship("User", back_populates="action_logs")
    
    # 索引定义
    __table_args__ = (
        Index('idx_action_analysis', user_id, action_type, create_time.desc()),
        Index('idx_target_object', target_type, target_id, create_time),
        Index('idx_time_range', create_time.desc()),
        Index('idx_client_ip', client_ip),
        {'comment': '用户行为日志表'}
    )

    def __repr__(self):
        return '<UserActionLog %r>' % str(self.log_id)+':'+str(self.action_type)+':'+str(self.target_type)+':'+str(self.user_id)
